package Model.DAO;

import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.HashMap;
/*
* 基础增删查改的sql生成器和一些重复使用的基本数据库连接语句
* */
public class BaseDao {
    private static InitialContext context = null;
    DataSource dataSource = null;
    String EntityName = null;
    //链接建立基模块
    public BaseDao(String EntityName) {
        try {
            this.EntityName = EntityName.toLowerCase();
            if (context == null) {
                context = new InitialContext();
            }
            dataSource = (DataSource) context.lookup("java:comp/env/jdbc/mysql");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //增加基模块
    protected<Entity> String insertEntitySql(Entity entity) throws Exception{
        Class claz = entity.getClass();
        StringBuilder sqlup = new StringBuilder();
        StringBuilder sqldown = new StringBuilder();
        sqlup.append("INSERT INTO ");
        sqlup.append(claz.getSimpleName().toLowerCase());
        sqlup.append(" (");
        sqldown.append("VALUES (");
        Field[] fields = claz.getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            if(field.get(entity)!=null){
                sqlup.append(field.getName()+",");
                if(field.getType().getSimpleName().equals("String"))
                    sqldown.append("\""+field.get(entity)+"\",");
                else if(field.getType().getSimpleName().equals("Date")){
                    sqldown.append("\""+ new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(field.get(entity))+"\",");
                }
                else
                    sqldown.append(field.get(entity)+",");
            }
        }
        sqlup.deleteCharAt(sqlup.length()-1);
        sqldown.deleteCharAt(sqldown.length()-1);
        sqlup.append(")");
        sqldown.append(")");
        sqlup.append(sqldown);
        return sqlup.toString();
    }
    protected<Entity> boolean insert(Entity entity){
        Connection conn = null;
        try{
            conn = dataSource.getConnection();
            int rst  = conn.prepareStatement(insertEntitySql(entity)).executeUpdate();
            conn.close();
            return rst==0?false:true;
            }
        catch (Exception e){
            close(conn);
            e.printStackTrace();
            return false;
        }
    }
    //删除基模块
    protected boolean delete(Long id){
        Connection conn= null;
        try{
            conn = dataSource.getConnection();
            PreparedStatement stm = conn.prepareStatement("DELETE FROM"+EntityName+" WHERE id=?");
            stm.setLong(1,id);
            int rst = stm.executeUpdate();
            close(conn);
            return rst==0?false:true;
        }
        catch (Exception e){
            close(conn);
            e.printStackTrace();
            return false;
        }
    }
    //查询基模块
    protected Object find(Long id){//仅适用于entity模型
        Connection conn= null;
        try{
            conn = dataSource.getConnection();
            PreparedStatement stm = conn.prepareStatement("select * FROM "+EntityName+" WHERE id=?");
            Class aClass = Class.forName("Model.Entity."+EntityName.substring(0,1).toUpperCase()+EntityName.substring(1));
            stm.setLong(1,id);
            ResultSet rst = stm.executeQuery();
            ResultSetMetaData rsmd = rst.getMetaData();
            Object cc = aClass.newInstance();
            Field[] fields = aClass.getDeclaredFields();
            HashMap<String,Field> test = new HashMap();
            for(Field field:fields){
                test.put(field.getName().toLowerCase(),field);
            }
            if(rst.next()){
                //此处反射将对应属性存入entity
                for (int i=0;i<rsmd.getColumnCount();i++){
                    String xx = rsmd.getColumnName(i+1);
                    Field temp = test.get(xx);
                    temp.setAccessible(true);
                    temp.set(cc,rst.getObject(i+1));
                }
                close(conn);
                return cc;
            }else {
                close(conn);
                return null;
            }
        }
        catch (Exception e){
            close(conn);
            e.printStackTrace();
            return null;
        }
    }
    //修改基模块
    protected<Entity> String modifyEntitySql(Entity entity) throws Exception{
        Class claz = entity.getClass();
        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE ");
        sql.append(claz.getSimpleName().toLowerCase());
        sql.append(" SET ");
        Field[] fields = claz.getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            sql.append(field.getName()+"=");
            switch (field.getType().getSimpleName()){
                case "String":
                    sql.append("'"+field.get(entity)+"',");
                    break;
                default:
                    sql.append(field.get(entity)+",");
                    break;
            }
        }
        sql.append("\b WHERE id=");
        sql.append(fields[0].get(entity));
        return sql.toString();
    }
    protected<Entity> boolean update(Entity entity){
        Connection conn = null;
        try{
            conn = dataSource.getConnection();
            int rst  = conn.prepareStatement(modifyEntitySql(entity)).executeUpdate();
            conn.close();
            return rst==0?false:true;
        }
        catch (Exception e){
            close(conn);
            e.printStackTrace();
            return false;
        }
    }
    //关闭连接基模块
    protected void close(Connection conn){
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //自增id基模块
    protected Long EntityCount(){
        Connection conn = null;
        try{
            conn = dataSource.getConnection();
            ResultSet rst = conn.prepareStatement("select * from "+EntityName+" u where u.id>=all(select id from "+EntityName+")").executeQuery();
            if(rst.next())
            {
                Long id =  (Long.parseLong(rst.getObject(1).toString())+1);
                close(conn);
                return id;
            }
            else{
                close(conn);
                return 1L;
            }
        }catch (Exception e){
            close(conn);
            e.printStackTrace();
            return 1L;
        }
    }
}
